/******************************************************************************

  File Name     : alg_face_recognition.cpp
  Version       : Initial Draft
  Author        : tongzhilin
  Created       : 2020/8/6
  Last Modified :
  Description   : alg_face_feature_v1, use alg: pfpld
  Function List :
  History       :
  1.Date        : 2020/8/6
    Author      : tongzhilin
    Modification: Created file

******************************************************************************/
#include "alg_face_lmk_v1.h"

#define DEV_TYPE            2               //1 cpu;2 gpu
#define DEV_ID              0               //gpu id, start 0
#define INPUT_BLOB_NUM      1
#define OUTPUT_BLOB_NUM     2
#define INPUT_N             1
#define INPUT_C             3
#define INPUT_H             112
#define INPUT_W             112

#define INPUT_MEAN          (0)
#define INPUT_STD           (255.f)

FacelmkV1::FacelmkV1(const char* _pJsonFile, const char* _pParamsFile) : 
    MxAlgBasic(_pJsonFile, _pParamsFile, DEV_TYPE, DEV_ID, 
    INPUT_BLOB_NUM, OUTPUT_BLOB_NUM, 
    INPUT_N, INPUT_C, INPUT_H, INPUT_W, 
    INPUT_MEAN, INPUT_MEAN, INPUT_MEAN, INPUT_STD)
{
    m_f32ScalX = alg_get_input_w() * 1.0f;
    m_f32ScalY = alg_get_input_h() * 1.0f;
}

FacelmkV1::~FacelmkV1()
{
    
}

bool FacelmkV1::ab_image_post()
{
    //just print output
    size_t begin = m_begin;
    size_t end = std::min(begin + m_max_batch, (size_t)m_input_batch);
    INT32 C = 0;
    INT32 H = 0;
    INT32 W = 0;
    INT32 S = 0;

    //MP_ASSERT(alg_get_output_blob_n() == 2);

    //cache flash
    alg_flash_output_blob();

    //lmks
    INT32 b = alg_get_output_blob_n()-1;
    C = m_s32vOutBlob_C[b];
    H = m_s32vOutBlob_H[b];
    W = m_s32vOutBlob_W[b];
    S = m_s32vOutBlob_W[b];
    for(UINT32 n = begin; n < end; n++)
    {
        INT32 s32NPosi = (n-begin)*C*H*S;
        float *pf32Val = m_vstOutputDataBlob[b].m_pfBlobdata + s32NPosi;
        //for (INT32 c = 0; c < C; c++)
        //for (INT32 h = 0; h < H; h++)
        m_pstFaceLmkResult[n].m_s32PointsNum = W/2;
        for (INT32 w = 0; w < W; w+=2) 
        {
            INT32 posi = w;
            //posi = (c * H+ h) * S + w;
            m_pstFaceLmkResult[n].m_stPoints[posi/2].m_f32X = pf32Val[posi] * m_f32ScalX;// 112 / 4096.f;
            m_pstFaceLmkResult[n].m_stPoints[posi/2].m_f32Y = pf32Val[posi+1] * m_f32ScalY;//112 / 4096.f;
            //MP_LOG_DBG("face landmark v1 1 pic[%d], npose:%d, w:%d, x:%f, y:%f\n", n, s32NPosi, w, 
                //m_pstFaceLmkResult[n].m_stPoints[posi/2].m_f32X, m_pstFaceLmkResult[n].m_stPoints[posi/2].m_f32Y);
        }
    }

    m_begin += m_max_batch;
    bool finish = (end == (size_t)m_input_batch)? true : false;
    if (finish)
    {
       m_begin = 0;
    }
    return finish;
}

INT32 FacelmkV1::alg_run_image(ALG_IMAGE_S* _pstImage, INT32 _s32MaxRet, void *_pstResult)
{
    bool bFinish = false;
    UINT64 u64TimeStart = 0;
    INT32 s32CurBatch = 0;

    CHECK_NON_NULL_POINTER(_pstImage, -1);

    //SVP_IMAGE_S* pstSvpImage = (SVP_IMAGE_S*)_pstImage;
    m_input_batch = 1;

    m_pstFaceLmkResult = (ALG_FACELMK_RESULT_S *)_pstResult;

    while (1)
    {
        TIME_START(u64TimeStart);
        ab_image_pre(IMG_PRE_TYPE_IMAGE, _pstImage);
        s32CurBatch = std::min(m_cur_batch, m_input_batch-m_begin);
        TIME_END(u64TimeStart, "Alg run image pre.model:%s, batch:%d, time: ", m_cJsonFile, s32CurBatch);

        TIME_START(u64TimeStart);
        ab_image_proc();
        TIME_END(u64TimeStart, "Alg run image proc.model:%s, batch:%d, time: ", m_cJsonFile, s32CurBatch);

        TIME_START(u64TimeStart);
        bFinish = ab_image_post();
        TIME_END(u64TimeStart, "Alg run image post.model:%s, batch:%d, time: ", m_cJsonFile, s32CurBatch);

        if (bFinish)
        {
            break;
        }
    }

    return 0;
}


